package com.airlines.crewassignment.domain.solver.move;

import java.util.Collection;
import java.util.Collections;
import java.util.Objects;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.optaplanner.core.impl.heuristic.move.AbstractMove;
import org.optaplanner.core.impl.score.director.ScoreDirector;

import com.airlines.crewassignment.domain.Crew;
import com.airlines.crewassignment.domain.CrewLinkLineRoster;
import com.airlines.crewassignment.domain.CrewPositionAssignment;

/**
 * @author xxxx
 * @date 2018年4月16日 
 * @description
 */
public class CrewChangeMove extends AbstractMove<CrewLinkLineRoster>{
	
	private CrewPositionAssignment crewPositionAssignment;
	private Crew toCrew;
	
	public CrewChangeMove(CrewPositionAssignment crewPositionAssignment,Crew toCrew){
		this.crewPositionAssignment = crewPositionAssignment;
		this.toCrew = toCrew;
	}

	@Override
	public boolean isMoveDoable(ScoreDirector<CrewLinkLineRoster> scoreDirector) {
		 return !Objects.equals(crewPositionAssignment.getCrew().getWorkcode(), toCrew.getWorkcode());
	}

	@Override
	public Collection<? extends Object> getPlanningEntities() {
		 return Collections.singletonList(crewPositionAssignment);
	}

	@Override
	public Collection<? extends Object> getPlanningValues() {
		  return Collections.singletonList(toCrew);
	}

	@Override
	protected AbstractMove<CrewLinkLineRoster> createUndoMove(ScoreDirector<CrewLinkLineRoster> scoreDirector) {
		return new CrewChangeMove(crewPositionAssignment,crewPositionAssignment.getCrew());
	}

	@Override
	protected void doMoveOnGenuineVariables(ScoreDirector<CrewLinkLineRoster> scoreDirector) {
		CrewLinkLineRosteringMoveHelpe.moveCrew(scoreDirector, crewPositionAssignment, toCrew);
	}

	@Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        } else if (o instanceof CrewChangeMove) {
        	CrewChangeMove other = (CrewChangeMove) o;
            return new EqualsBuilder()
                    .append(crewPositionAssignment, other.crewPositionAssignment)
                    .append(toCrew, other.toCrew)
                    .isEquals();
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder()
                .append(crewPositionAssignment)
                .append(toCrew)
                .toHashCode();
    }

    @Override
    public String toString() {
        return crewPositionAssignment.getPosition().getPositionKey() + " {" + crewPositionAssignment.getCrew().getWorkcode() + " -> " + toCrew.getWorkcode() + "}";
    }
	
}
